From 0ba5a7a2c3d5dd1adff874adbc2c9be3198ad1f9 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 14 Jun 2015 11:16:46 -0700 Subject: [PATCH] Fix resolution with `default-features = false` There was previously a bug in resolve where turning off the default set of features would cause resolve to not correctly settle on the set of features activated for a package. If one dependency turned off all features, and then the next dependency to be activated only turned on the default feature, the default feature wouldn't actually end up getting activated. This commit alters the check to see if the package has been previously activated to more rigorously check to see if the 'default' feature is activated previously. If a dependency doesn't use the default feature, or if the package itself does not have the feature "default", then the package is considered activated, but otherwise it needs to go through another cycle of resolution. --- src/cargo/core/resolver/mod.rs | 6 +++-- tests/support/mod.rs | 4 ++- tests/test_cargo_features.rs | 46 ++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/resolver/mod.rs b/src/cargo/core/resolver/mod.rs index 2f9bd5725..a72d7a534 100644 --- a/src/cargo/core/resolver/mod.rs +++ b/src/cargo/core/resolver/mod.rs @@ -234,12 +234,14 @@ fn flag_activated(cx: &mut Context, } Method::Everything => return false, }; + + let has_default_feature = summary.features().contains_key("default"); match cx.resolve.features(id) { Some(prev) => { features.iter().all(|f| prev.contains(f)) && - (!use_default || prev.contains("default")) + (!use_default || prev.contains("default") || !has_default_feature) } - None => features.len() == 0, + None => features.len() == 0 && (!use_default || !has_default_feature) } } diff --git a/tests/support/mod.rs b/tests/support/mod.rs index fa004f254..fce7fd199 100644 --- a/tests/support/mod.rs +++ b/tests/support/mod.rs @@ -134,7 +134,9 @@ impl ProjectBuilder { pub fn process>(&self, program: T) -> ProcessBuilder { let mut p = process(program).unwrap(); - p.cwd(&self.root()).env("HOME", &paths::home()); + p.cwd(&self.root()) + .env("HOME", &paths::home()) + .env_remove("CARGO_HOME"); return p; } diff --git a/tests/test_cargo_features.rs b/tests/test_cargo_features.rs index d46d0d7ae..3d86dcedf 100644 --- a/tests/test_cargo_features.rs +++ b/tests/test_cargo_features.rs @@ -695,3 +695,49 @@ test!(no_rebuild_when_frobbing_default_feature { assert_that(p.cargo("build"), execs().with_status(0).with_stdout("")); assert_that(p.cargo("build"), execs().with_status(0).with_stdout("")); }); + +test!(unions_work_with_no_default_features { + let p = project("foo") + .file("Cargo.toml", r#" + [package] + name = "foo" + version = "0.1.0" + authors = [] + + [dependencies] + a = { path = "a" } + b = { path = "b" } + "#) + .file("src/lib.rs", r#" + extern crate a; + pub fn foo() { a::a(); } + "#) + .file("b/Cargo.toml", r#" + [package] + name = "b" + version = "0.1.0" + authors = [] + + [dependencies] + a = { path = "../a", features = [], default-features = false } + "#) + .file("b/src/lib.rs", "") + .file("a/Cargo.toml", r#" + [package] + name = "a" + version = "0.1.0" + authors = [] + + [features] + default = ["f1"] + f1 = [] + "#) + .file("a/src/lib.rs", r#" + #[cfg(feature = "f1")] + pub fn a() {} + "#); + + assert_that(p.cargo_process("build"), execs().with_status(0)); + assert_that(p.cargo("build"), execs().with_status(0).with_stdout("")); + assert_that(p.cargo("build"), execs().with_status(0).with_stdout("")); +}); -- 2.30.2